import CryptoJS from 'crypto-js';
import {Button} from '@kintone/kintone-ui-component/esm/js';
import {default as swal} from 'sweetalert2';

(function(PLUGIN_ID) {
  'use strict';

  const message = {
    'en': {
      'msg_empty_subject': 'Meeting title cannot be empty',
      'msg_empty_startTime': 'StartTime cannot be empty',
      'msg_empty_endTime': 'EndTime cannot be empty',
      'msg_wrong_datetime': 'End time should be greater than start time',
      'msg_btn_cancel': 'Cancel this meeting',
      'msg_alert_cancel_title': 'Do you want to cancel this meeting?',
      'msg_alert_confirm': 'Yes',
      'msg_alert_cancel': 'No',
      'msg_alert_cancel_success': 'Canceled the meeting successfully',
      'msg_alert_cancel_failure': 'Failed to cancel the meeting',
      'msg_setting_error': 'Configuration error, field does not exist or has no permissions, please confirm'
    },
    'zh': {
      'msg_empty_subject': '会议标题不能为空',
      'msg_empty_startTime': '开始时间不能为空',
      'msg_empty_endTime': '结束时间不能为空',
      'msg_wrong_datetime': '结束时间应大于开始时间',
      'msg_btn_cancel': '取消会议',
      'msg_alert_cancel_title': '你想取消这个会议?',
      'msg_alert_confirm': '是',
      'msg_alert_cancel': '否',
      'msg_alert_cancel_success': '取消会议成功',
      'msg_alert_cancel_failure': '取消会议失败',
      'msg_setting_error': '配置错误，字段不存在或没有权限，请确认'
    }
  };

  const lang = kintone.getLoginUser().language;
  const i18n = (lang in message) ? message[lang] : message['zh'];
  let config;

  const validateConfig = () => {
    config = kintone.plugin.app.getConfig(PLUGIN_ID);
    return config !== null;
  };

  if (!validateConfig()) {
    swal.fire({
      icon: 'error',
      title: i18n.msg_setting_error
    });
    return;
  }

  const checkFields = (fieldsCode, fieldsType, evnetRecord) => {
    if (fieldsCode.length > 0) {
      for (let i = 0; i < fieldsCode.length; i++) {
        if (!evnetRecord.hasOwnProperty(fieldsCode[i]) || evnetRecord[fieldsCode[i]]['type'] !== fieldsType) {
          swal.fire({
            icon: 'error',
            title: i18n.msg_setting_error
          });
          return false;
        }
      }
    }
    return true;
  };

  const randomNumber = (min, max) => {
    return Math.round(Math.random() * (max - min)) + min;
  };

  const nowTime = () => {
    const dateTime = Date.now();
    return Math.floor(dateTime / 1000);
  };

  const getTime = (date) => {
    const tmpDateTime = date.split('T')[0].replace(/-/g, '/') + ' ' + date.split('T')[1].split('.')[0];
    const dateWithTz = new Date(tmpDateTime.substring(0, tmpDateTime.length - 1));
    dateWithTz.setHours(dateWithTz.getHours() + 8);
    const dateTime = dateWithTz.getTime();
    return Math.floor(dateTime / 1000);
  };

  const createHeaders = (secretId, randomNum, now, appId, signature) => {
    return {
      'Content-Type': 'application/json',
      'X-TC-Key': secretId,
      'X-TC-Timestamp': now.toString(),
      'X-TC-Nonce': randomNum.toString(),
      'AppId': appId,
      'X-TC-Signature': btoa(signature)
    };
  };

  const createSignature = (secretId, randomNum, now, httpMethod, url, params) => {
    const headerString = 'X-TC-Key=' + secretId + '&X-TC-Nonce=' + randomNum + '&X-TC-Timestamp=' + now;
    let stringToSign = httpMethod + '\n' +
      headerString + '\n' +
      url + '\n';
    if (typeof params === 'undefined') {
      stringToSign += '';
    } else {
      stringToSign += JSON.stringify(params);
    }
    const key = CryptoJS.enc.Utf8.parse(config.secretKey);
    const content = CryptoJS.enc.Utf8.parse(stringToSign);
    return CryptoJS.enc.Hex.stringify(CryptoJS.HmacSHA256(content, key));
  };

  const addMeeting = {
    httpMethod: 'POST',
    url: '/v1/meetings',
    requestUrl: 'https://api.meeting.qq.com/v1/meetings',
    addMeetingParams: (account, subject, startTime, endTime) => {
      return {
        userid: account,
        subject: subject,
        start_time: getTime(startTime).toString(),
        end_time: getTime(endTime).toString(),
        instanceid: 1,
        type: 0,
        settings: {}
      };
    }
  };

  const modifyMeeting = {
    httpMethod: 'PUT',
    url: (meetingId) => {
      return '/v1/meetings/' + meetingId;
    },
    requestUrl: (meetingId, account) => {
      return 'https://api.meeting.qq.com/v1/meetings/' + meetingId;
    },
    modifyMeetingParams: (account, subject, startTime, endTime) => {
      return {
        userid: account,
        subject: subject,
        start_time: getTime(startTime).toString(),
        end_time: getTime(endTime).toString(),
        instanceid: 1,
        settings: {}
      };
    }
  };

  const getMeeting = {
    httpMethod: 'GET',
    url: (meetingId, account) => {
      return '/v1/meetings/' + meetingId + '?'
        + '&userid=' + account +
        '&instanceid=1';
    },
    requestUrl: (meetingId, account) => {
      return 'https://api.meeting.qq.com/v1/meetings/' + meetingId + '?'
        + '&userid=' + account +
        '&instanceid=1';
    }
  };

  const cancelMeeting = {
    httpMethod: 'POST',
    url: (meetingId) => {
      return '/v1/meetings/' + meetingId + '/cancel';
    },
    requestUrl: (meetingId) => {
      return 'https://api.meeting.qq.com/v1/meetings/' + meetingId + '/cancel';
    },
    cancelMeetingParams: (account) => {
      return {
        userid: account,
        instanceid: 1,
        reason_code: 1
      };
    }
  };

  kintone.events.on('app.record.detail.show', function(event) {
    const record = event.record;
    if (!checkFields([config.meetingId], 'SINGLE_LINE_TEXT', record)) return event;
    const meetingId = record[config.meetingId]['value'];
    const space = kintone.app.record.getHeaderMenuSpaceElement();
    const button = new Button({text: i18n.msg_btn_cancel, type: 'submit'});
    const div = document.createElement('div');

    const randomNumForGet = randomNumber(10000, 99999);
    const nowForGet = nowTime();
    const signatureForGet = createSignature(config.secretId, randomNumForGet, nowForGet, getMeeting.httpMethod,
      getMeeting.url(meetingId, config.account));
    const getMeetingHeaders = createHeaders(config.secretId, randomNumForGet, nowForGet, config.appId, signatureForGet);
    kintone.proxy(getMeeting.requestUrl(meetingId, config.account), getMeeting.httpMethod, getMeetingHeaders, {}).then(function(response) {
      const responseJson = window.JSON.parse(!response[0] ? '{}' : response[0]);
      if (responseJson['meeting_info_list'][0]['status'] !== 'MEETING_STATE_CANCELLED') {
        div.appendChild(button.render());
        space.appendChild(div);
      }
    }).catch(function(error) {
      console.log(error);
    });

    button.on('click', () => {
      swal.fire({
        title: i18n.msg_alert_cancel_title,
        icon: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#3085d6',
        cancelButtonColor: '#d33',
        confirmButtonText: i18n.msg_alert_confirm,
        cancelButtonText: i18n.msg_alert_cancel
      }).then((result) => {
        if (result.value) {
          cancel();
        }
      });
    });

    const cancel = () => {
      const randomNum = randomNumber(10000, 99999);
      const now = nowTime();
      const params = cancelMeeting.cancelMeetingParams(config.account);
      const signature = createSignature(config.secretId, randomNum, now, cancelMeeting.httpMethod, cancelMeeting.url(meetingId), params);
      const cancelMeetingHeaders = createHeaders(config.secretId, randomNum, now, config.appId, signature);
      kintone.proxy(cancelMeeting.requestUrl(meetingId), cancelMeeting.httpMethod, cancelMeetingHeaders, params).then(function(response) {
        if (response[1] === 200) {
          swal.fire(i18n.msg_alert_cancel_success).then((result) => {
            if (result.value) {
              window.location.reload();
            }
          });
        } else {
          swal.fire(i18n.msg_alert_cancel_failure);
        }
      }).catch(function(error) {
        console.log(error);
      });
    };

    return event;
  });

  kintone.events.on(['app.record.create.show', 'app.record.edit.show'], function(event) {
    const record = event.record;
    if (!checkFields([config.meetingUrl, config.meetingId], 'SINGLE_LINE_TEXT', record)) return event;
    record[config.meetingUrl]['disabled'] = true;
    record[config.meetingId]['disabled'] = true;
    return event;
  });

  kintone.events.on('app.record.index.edit.show', function(event) {
    const record = event.record;
    if (!checkFields([config.meetingSubject, config.meetingUrl, config.meetingId], 'SINGLE_LINE_TEXT', record)) return event;
    if (!checkFields([config.startTime, config.endTime], 'DATETIME', record)) return event;
    record[config.meetingSubject]['disabled'] = true;
    record[config.startTime]['disabled'] = true;
    record[config.endTime]['disabled'] = true;
    record[config.meetingId]['disabled'] = true;
    record[config.meetingUrl]['disabled'] = true;

    return event;
  });

  kintone.events.on('app.record.create.submit', function(event) {
    const record = event.record;
    if (!checkFields([config.meetingSubject, config.meetingUrl, config.meetingId], 'SINGLE_LINE_TEXT', record)) return false;
    if (!checkFields([config.startTime, config.endTime], 'DATETIME', record)) return false;
    const subject = record[config.meetingSubject]['value'];
    const startTime = record[config.startTime]['value'];
    const endTime = record[config.endTime]['value'];

    if (typeof subject === 'undefined' || subject.length <= 0) {
      swal.fire({
        icon: 'error',
        title: i18n.msg_empty_subject
      });
      return false;
    }

    if (typeof startTime === 'undefined' || startTime.length <= 0) {
      swal.fire({
        icon: 'error',
        title: i18n.msg_empty_startTime
      });
      return false;
    }

    if (typeof endTime === 'undefined' || endTime.length <= 0) {
      swal.fire({
        icon: 'error',
        title: i18n.msg_empty_endTime
      });
      return false;
    }

    if (getTime(startTime) >= getTime(endTime)) {
      swal.fire({
        icon: 'error',
        title: i18n.msg_wrong_datetime
      });
      return false;
    }

    const randomNum = randomNumber(10000, 99999);
    const now = nowTime();
    const params = addMeeting.addMeetingParams(config.account, subject, startTime, endTime);
    const signature = createSignature(config.secretId, randomNum, now, addMeeting.httpMethod, addMeeting.url, params);
    const addMeetingHeaders = createHeaders(config.secretId, randomNum, now, config.appId, signature);

    return new Promise(function(resolve) {
      kintone.proxy(addMeeting.requestUrl, addMeeting.httpMethod, addMeetingHeaders, params).then(function(response) {
        const responseJson = window.JSON.parse(!response[0] ? '{}' : response[0]);
        record[config.meetingUrl]['value'] = responseJson['meeting_info_list'][0]['join_url'];
        record[config.meetingId]['value'] = responseJson['meeting_info_list'][0]['meeting_id'];
        return resolve(event);
      }).catch(function(error) {
        console.log(error);
      });
    });
  });

  kintone.events.on('app.record.edit.submit', function(event) {
    const record = event.record;
    if (!checkFields([config.meetingSubject, config.meetingId], 'SINGLE_LINE_TEXT', record)) return false;
    if (!checkFields([config.startTime, config.endTime], 'DATETIME', record)) return false;
    const subject = record[config.meetingSubject]['value'];
    const startTime = record[config.startTime]['value'];
    const endTime = record[config.endTime]['value'];
    const meetingId = record[config.meetingId]['value'];

    if (typeof subject === 'undefined' || subject.length <= 0) {
      swal.fire({
        icon: 'error',
        title: i18n.msg_empty_subject
      });
      return false;
    }

    if (typeof startTime === 'undefined' || startTime.length <= 0) {
      swal.fire({
        icon: 'error',
        title: i18n.msg_empty_startTime
      });
      return false;
    }

    if (typeof endTime === 'undefined' || endTime.length <= 0) {
      swal.fire({
        icon: 'error',
        title: i18n.msg_empty_endTime
      });
      return false;
    }

    if (getTime(startTime) >= getTime(endTime)) {
      swal.fire({
        icon: 'error',
        title: i18n.msg_wrong_datetime
      });
      return false;
    }

    const randomNum = randomNumber(10000, 99999);
    const now = nowTime();
    const params = modifyMeeting.modifyMeetingParams(config.account, subject, startTime, endTime);
    const signature = createSignature(config.secretId, randomNum, now, modifyMeeting.httpMethod, modifyMeeting.url(meetingId), params);
    const modifyMeetingHeaders = createHeaders(config.secretId, randomNum, now, config.appId, signature);

    return new Promise(function(resolve) {
      kintone.proxy(modifyMeeting.requestUrl(meetingId), modifyMeeting.httpMethod, modifyMeetingHeaders, params).then(function(response) {
        if (response[1] === 200) {
          return resolve(event);
        }
      }).catch(function(error) {
        console.log(error);
      });
    });
  });
})(kintone.$PLUGIN_ID);